#include "mpnetclientfactory.h"

CMpNetClientFactory::CMpNetClientFactory()
{
}

CMpNetClientFactory::~CMpNetClientFactory()
{
    //TODO: 释放所有的
}

int CMpNetClientFactory::Init(const char* pszBuffer, int iBufferSize, int iObjectCount)
{
    CT_ASSERT((size_t)CountSize(iObjectCount) == (size_t)iBufferSize);

    int iRet = 0;
    iRet = m_stMgr.Init(pszBuffer, iObjectCount, sizeof(CMpNetClient), LIST_COUNT, INDEX_COUNT);
    CHECK_RETURN(iRet);

    return 0;
}

CMpNetClient* CMpNetClientFactory::New()
{
    int i = m_stMgr.InfoListAlloc(ALLOC_INDEX, USED_LIST);
    if (i < 0)
    {
        CT_WARNING((""));
        return NULL;
    }

    // STATUS_INDEX中要设为IDLE
    int iRet = m_stMgr.InfoListMove(i, STATUS_INDEX, IDLE_LIST);
    if (iRet != 0)
    {
        CT_WARNING(("move client to idle list error, ret %d", iRet));
        return NULL;
    }

    CMpNetClient* pstClient = new (&m_stMgr[i]) CMpNetClient;
    return pstClient;
}

int CMpNetClientFactory::Delete(CMpNetClient* pstClient)
{
    int i = CalcObjectPos(pstClient);

    // 空闲
    m_stMgr.InfoListMove(i, STATUS_INDEX, FREE_LIST);    

    // 未使用
    m_stMgr.InfoListMove(i, ALLOC_INDEX, FREE_LIST);

    // 析构
    pstClient->~CMpNetClient();
    return 0;
}

CMpNetClient* CMpNetClientFactory::AllocOneIdle()
{
    int i = m_stMgr.InfoListAlloc(STATUS_INDEX, BUSY_LIST, 
				m_stMgr.ListInfo(IDLE_LIST, STATUS_INDEX), m_stMgr.ListInfo(BUSY_LIST, STATUS_INDEX));
    if (i < 0)
    {
        CT_WARNING(("alloc idle client error, free = %d, idle = %d, busy = %d, closing = %d, total = %d", 
            m_stMgr.Size(FREE_LIST, STATUS_INDEX), m_stMgr.Size(IDLE_LIST, STATUS_INDEX), 
            m_stMgr.Size(BUSY_LIST, STATUS_INDEX), m_stMgr.Size(CLOSING_LIST, STATUS_INDEX), m_stMgr.GetObjectCount()));
        return NULL;
    }

    // 需要保证这个节点是已经Alloc过的
    CT_ASSERT(m_stMgr.Flag(i, ALLOC_INDEX) == USED_LIST);

    // 这里不用再new了
    return (CMpNetClient*) &m_stMgr[i];
}

int CMpNetClientFactory::SetIdle(CMpNetClient* pstClient)
{
    int i = CalcObjectPos(pstClient);
    if (m_stMgr.Flag(i, STATUS_INDEX) != BUSY_LIST)
    {
        CT_WARNING((""));
        return -1;
    }

    return m_stMgr.InfoListMove(i, STATUS_INDEX, IDLE_LIST);
}

int CMpNetClientFactory::SetBusy(CMpNetClient* pstClient)
{
    int i = CalcObjectPos(pstClient);
    if (m_stMgr.Flag(i, STATUS_INDEX) != IDLE_LIST)
    {
        CT_WARNING((""));
        return -1;
    }

    return m_stMgr.InfoListMove(i, STATUS_INDEX, BUSY_LIST);
}

int CMpNetClientFactory::SetClosing(CMpNetClient* pstClient)
{
    int i = CalcObjectPos(pstClient);
    if (m_stMgr.Flag(i, STATUS_INDEX) != IDLE_LIST)
    {
        CT_WARNING((""));
        return -1;
    }

    return m_stMgr.InfoListMove(i, STATUS_INDEX, CLOSING_LIST);
}
